package category

import (
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/model"
	"errors"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type CategoryRepository interface {
	base.Repository
	FindAll(visualType string, user *model.User) ([]*Vo, error)
	FindByCategoryValue(mdl *model.DataUserModel) (*Category, error)
}

func NewCategoryRepository() CategoryRepository {
	return &categoryRepository{
		base.RepositoryStruct{
			CollectionName: server.CgsPortalCategoryCollectionName,
		},
	}
}

type categoryRepository struct {
	base.RepositoryStruct
}

// 查找用户下的所有分类
func (c *categoryRepository) FindAll(visualType string, user *model.User) ([]*Vo, error) {
	if err := c.CheckDB(); err != nil {
		return nil, err
	}
	filter := bson.M{
		"VisualType": visualType,
		"$or": bson.A{
			bson.M{
				"tenantId": user.TenantId,
			},
			bson.M{
				"tenantId": nil,
			},
		},
	}
	var result []*Vo
	err := c.Mongo.FindMany(c.CollectionName, filter, &result)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// 根据id查找某个分类
func (c *categoryRepository) FindOne(mdl *model.DataUserModel) (interface{}, error) {
	if category, ok := mdl.Data.(*Category); ok {
		if err := c.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"ID": category.ID,
		}
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		category.ResolveFilter(category, mdl.User, &filter)
		result := &Category{}
		find, err := c.Mongo.FindOne(c.CollectionName, filter, result)
		if err != nil {
			return nil, err
		}
		if !find {
			return nil, errors.New("category not found")
		}
		return category, nil
	} else {
		return nil, errors.New("Category type error")
	}
}

// 根据 CategoryValue 查找
func (c *categoryRepository) FindByCategoryValue(mdl *model.DataUserModel) (*Category, error) {
	if category, ok := mdl.Data.(*Category); ok {
		if err := c.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{
			"CategoryValue": category.CategoryValue,
			"VisualType":    category.VisualType,
		}
		category.ResolveFilter(category, mdl.User, &filter)
		result := &Category{}
		find, err := c.Mongo.FindOne(c.CollectionName, filter, result)
		if err != nil {
			return nil, err
		}
		if !find {
			return nil, nil
		}
		return category, nil
	} else {
		return nil, errors.New("Category type error")
	}
}

// 添加分类
func (c *categoryRepository) Insert(mdl *model.DataUserModel) error {
	if category, ok := mdl.Data.(*Category); ok {
		if err := c.CheckDB(); err != nil {
			return err
		}
		category.ResolveEntity(category, mdl.User)
		_, err := c.Mongo.InsertOne(c.CollectionName, category)
		return err
	} else {
		return errors.New("Category type error")
	}
}

// 修改分类
func (c *categoryRepository) Update(mdl *model.DataUserModel) error {
	if category, ok := mdl.Data.(*Category); ok {
		if err := c.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": category.ID,
		}
		category.ResolveFilter(category, mdl.User, &filter)
		set := bson.M{}
		if category.CategoryValue != "" {
			set["CategoryValue"] = category.CategoryValue
		}
		if category.CategoryKey != "" {
			set["CategoryKey"] = category.CategoryKey
		}
		category.ResolveUpdateCondition(category, mdl.User, &set)
		update := bson.M{
			"$set": set,
		}
		_, err := c.Mongo.UpdateOne(c.CollectionName, filter, update)
		return err
	} else {
		return errors.New("Category type error")
	}
}

// 删除分类
func (c *categoryRepository) Delete(mdl *model.DataUserModel) error {
	if category, ok := mdl.Data.(*Category); ok {
		if err := c.CheckDB(); err != nil {
			return err
		}
		filter := bson.M{
			"ID": category.ID,
		}
		_, err := c.Mongo.DeleteOne(c.CollectionName, filter)
		return err
	} else {
		return errors.New("Category type error")
	}
}

// Find 查询分类数据
func (c *categoryRepository) Find(mdl *model.DataUserModel) (interface{}, error) {
	category, ok := mdl.Data.(*Category)
	if !ok {
		return nil, model.NewTypeError("category")
	}
	if err := c.CheckDB(); err != nil {
		return nil, err
	}

	filter := bson.M{}
	if mdl.Filter != nil {
		filter = *mdl.Filter
	}
	option := options.FindOptions{}
	if mdl.Options != nil {
		option = *mdl.Options
	}

	category.ResolveFilter(category, mdl.User, &filter)

	var result = []Category{}
	err := c.Mongo.FindMany(c.CollectionName, filter, &result, &option)

	return result, err
}
